"""
交易服务事件管理模块
====================

提供事件定义、事件管理器和事件处理机制
用于交易系统中的异步事件通信和状态同步
"""

# 确保项目根目录在Python路径中

# 统一路径管理
from backend.shared import PathManager
PathManager().setup_paths()
import sys
import os

import asyncio
import logging
from enum import Enum
from typing import Dict, List, Callable, Any, Optional
from datetime import datetime
import json
import uuid

class TradingTradingEventType(Enum):
    """交易服务事件类型枚举"""
    # 订单事件
    ORDER_CREATED = "order_created"
    ORDER_SUBMITTED = "order_submitted"
    ORDER_CANCELLED = "order_cancelled"
    ORDER_REJECTED = "order_rejected"
    ORDER_PARTIAL_FILLED = "order_partial_filled"
    ORDER_FILLED = "order_filled"
    
    # 成交事件
    TRADE_FILLED = "trade_filled"
    TRADE_UPDATED = "trade_updated"
    
    # 持仓事件
    POSITION_OPENED = "position_opened"
    POSITION_CLOSED = "position_closed"
    POSITION_UPDATED = "position_updated"
    
    # 资金事件
    ACCOUNT_UPDATED = "account_updated"
    BALANCE_CHANGED = "balance_changed"
    
    # 网关事件
    GATEWAY_CONNECTED = "gateway_connected"
    GATEWAY_DISCONNECTED = "gateway_disconnected"
    GATEWAY_ERROR = "gateway_error"
    
    # 策略事件
    STRATEGY_STARTED = "strategy_started"
    STRATEGY_STOPPED = "strategy_stopped"
    STRATEGY_ERROR = "strategy_error"
    
    # 风控事件
    RISK_WARNING = "risk_warning"
    RISK_BLOCKED = "risk_blocked"
    
    # 系统事件
    SYSTEM_STARTUP = "system_startup"
    SYSTEM_SHUTDOWN = "system_shutdown"
    SYSTEM_ERROR = "system_error"

class Event:
    """事件对象"""
    
    def __init__(self, event_type: TradingTradingEventType, data: Dict[str, Any], 
                 source: Optional[str] = None, user_id: Optional[str] = None):
        """
        初始化事件
        
        Args:
            event_type: 事件类型
            data: 事件数据
            source: 事件源
            user_id: 用户ID
        """
        self.id = str(uuid.uuid4())
        self.event_type = event_type
        self.data = data
        self.source = source or "trading-service"
        self.user_id = user_id
        self.timestamp = datetime.utcnow()
        self.processed = False
        self.retry_count = 0
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return {
            "id": self.id,
            "event_type": self.event_type.value,
            "data": self.data,
            "source": self.source,
            "user_id": self.user_id,
            "timestamp": self.timestamp.isoformat(),
            "processed": self.processed,
            "retry_count": self.retry_count
        }
    
    def to_json(self) -> str:
        """转换为JSON字符串"""
        return json.dumps(self.to_dict(), default=str)
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'Event':
        """从字典创建事件"""
        event = cls(
            event_type=TradingEventType(data["event_type"]),
            data=data["data"],
            source=data.get("source"),
            user_id=data.get("user_id")
        )
        event.id = data["id"]
        event.timestamp = datetime.fromisoformat(data["timestamp"])
        event.processed = data.get("processed", False)
        event.retry_count = data.get("retry_count", 0)
        return event
    
    @classmethod
    def from_json(cls, json_str: str) -> 'Event':
        """从JSON字符串创建事件"""
        return cls.from_dict(json.loads(json_str))

class EventHandler:
    """事件处理器基类"""
    
    def __init__(self, name: str):
        self.name = name
        self.logger = logging.getLogger(f"{__name__}.{name}")
    
    async def handle(self, event: Event) -> bool:
        """
        处理事件
        
        Args:
            event: 事件对象
            
        Returns:
            处理是否成功
        """
        raise NotImplementedError
    
    def can_handle(self, event_type: TradingEventType) -> bool:
        """
        检查是否可以处理指定类型的事件
        
        Args:
            event_type: 事件类型
            
        Returns:
            是否可以处理
        """
        return True

class EventManager:
    """事件管理器"""
    
    def __init__(self, redis_client=None):
        """
        初始化事件管理器
        
        Args:
            redis_client: Redis客户端，用于事件持久化和分布式处理
        """
        self.redis_client = redis_client
        self.logger = logging.getLogger(__name__)
        
        # 事件处理器注册表
        self._handlers: Dict[TradingEventType, List[EventHandler]] = {}
        self._global_handlers: List[EventHandler] = []
        
        # 事件队列
        self._event_queue: asyncio.Queue = asyncio.Queue()
        self._processing = False
        
        # 统计信息
        self._published_count = 0
        self._processed_count = 0
        self._failed_count = 0
        
        self.logger.info("事件管理器初始化完成")
    
    def register_handler(self, event_type: TradingEventType, handler: EventHandler):
        """
        注册事件处理器
        
        Args:
            event_type: 事件类型
            handler: 事件处理器
        """
        if event_type not in self._handlers:
            self._handlers[event_type] = []
        
        self._handlers[event_type].append(handler)
        self.logger.info(f"注册事件处理器: {handler.name} -> {event_type.value}")
    
    def register_global_handler(self, handler: EventHandler):
        """
        注册全局事件处理器（处理所有事件）
        
        Args:
            handler: 事件处理器
        """
        self._global_handlers.append(handler)
        self.logger.info(f"注册全局事件处理器: {handler.name}")
    
    def unregister_handler(self, event_type: TradingEventType, handler: EventHandler):
        """
        取消注册事件处理器
        
        Args:
            event_type: 事件类型
            handler: 事件处理器
        """
        if event_type in self._handlers:
            self._handlers[event_type] = [h for h in self._handlers[event_type] if h != handler]
            self.logger.info(f"取消注册事件处理器: {handler.name} -> {event_type.value}")
    
    async def publish(self, event_type: TradingEventType, data: Dict[str, Any], 
                     source: Optional[str] = None, user_id: Optional[str] = None):
        """
        发布事件
        
        Args:
            event_type: 事件类型
            data: 事件数据
            source: 事件源
            user_id: 用户ID
        """
        event = Event(event_type, data, source, user_id)
        
        # 将事件加入队列
        await self._event_queue.put(event)
        
        # 如果有Redis客户端，持久化事件
        if self.redis_client:
            try:
                await self.redis_client.lpush(
                    f"events:{event_type.value}",
                    event.to_json()
                )
                # 设置过期时间（7天）
                await self.redis_client.expire(f"events:{event_type.value}", 7 * 24 * 3600)
            except Exception as e:
                self.logger.error(f"事件持久化失败: {e}")
        
        self._published_count += 1
        self.logger.debug(f"发布事件: {event_type.value} - {event.id}")
        
        # 如果处理器没有运行，启动处理
        if not self._processing:
            asyncio.create_task(self._process_events())
    
    async def _process_events(self):
        """处理事件队列"""
        if self._processing:
            return
        
        self._processing = True
        self.logger.info("开始处理事件队列")
        
        try:
            while True:
                try:
                    # 从队列获取事件，超时5秒
                    event = await asyncio.wait_for(self._event_queue.get(), timeout=5.0)
                    await self._handle_event(event)
                    self._event_queue.task_done()
                    
                except asyncio.TimeoutError:
                    # 队列为空，停止处理
                    break
                except Exception as e:
                    self.logger.error(f"事件处理异常: {e}")
                    self._failed_count += 1
        
        finally:
            self._processing = False
            self.logger.info("事件队列处理完成")
    
    async def _handle_event(self, event: Event):
        """
        处理单个事件
        
        Args:
            event: 事件对象
        """
        try:
            # 获取事件类型的处理器
            handlers = self._handlers.get(event.event_type, [])
            
            # 添加全局处理器
            all_handlers = handlers + [h for h in self._global_handlers if h.can_handle(event.event_type)]
            
            if not all_handlers:
                self.logger.warning(f"没有找到事件处理器: {event.event_type.value}")
                return
            
            # 并发处理所有处理器
            tasks = []
            for handler in all_handlers:
                task = asyncio.create_task(self._execute_handler(handler, event))
                tasks.append(task)
            
            # 等待所有处理器完成
            results = await asyncio.gather(*tasks, return_exceptions=True)
            
            # 检查处理结果
            success_count = 0
            for i, result in enumerate(results):
                if isinstance(result, Exception):
                    self.logger.error(f"处理器 {all_handlers[i].name} 处理事件失败: {result}")
                elif result:
                    success_count += 1
            
            if success_count > 0:
                event.processed = True
                self._processed_count += 1
                self.logger.debug(f"事件处理完成: {event.event_type.value} - {event.id}")
            else:
                self.logger.error(f"所有处理器都处理失败: {event.event_type.value} - {event.id}")
                self._failed_count += 1
        
        except Exception as e:
            self.logger.error(f"事件处理异常: {e}")
            self._failed_count += 1
    
    async def _execute_handler(self, handler: EventHandler, event: Event) -> bool:
        """
        执行单个事件处理器
        
        Args:
            handler: 事件处理器
            event: 事件对象
            
        Returns:
            处理是否成功
        """
        try:
            return await handler.handle(event)
        except Exception as e:
            self.logger.error(f"处理器 {handler.name} 执行异常: {e}")
            return False
    
    def get_statistics(self) -> Dict[str, int]:
        """
        获取事件处理统计信息
        
        Returns:
            统计信息字典
        """
        return {
            "published_count": self._published_count,
            "processed_count": self._processed_count,
            "failed_count": self._failed_count,
            "queue_size": self._event_queue.qsize(),
            "handler_count": sum(len(handlers) for handlers in self._handlers.values()) + len(self._global_handlers)
        }
    
    async def replay_events(self, event_type: TradingEventType, limit: int = 100) -> List[Event]:
        """
        重放事件（从Redis获取历史事件）
        
        Args:
            event_type: 事件类型
            limit: 获取数量限制
            
        Returns:
            事件列表
        """
        if not self.redis_client:
            return []
        
        try:
            events_json = await self.redis_client.lrange(f"events:{event_type.value}", 0, limit - 1)
            events = []
            
            for event_json in events_json:
                try:
                    event = Event.from_json(event_json)
                    events.append(event)
                except Exception as e:
                    self.logger.error(f"事件反序列化失败: {e}")
            
            return events
        
        except Exception as e:
            self.logger.error(f"事件重放失败: {e}")
            return []
    
    async def cleanup_old_events(self, days: int = 7):
        """
        清理旧事件
        
        Args:
            days: 保留天数
        """
        if not self.redis_client:
            return
        
        try:
            # 获取所有事件类型的键
            pattern = "events:*"
            keys = await self.redis_client.keys(pattern)
            
            cutoff_time = datetime.utcnow() - timedelta(days=days)
            
            for key in keys:
                # 获取所有事件
                events_json = await self.redis_client.lrange(key, 0, -1)
                valid_events = []
                
                for event_json in events_json:
                    try:
                        event = Event.from_json(event_json)
                        if event.timestamp > cutoff_time:
                            valid_events.append(event_json)
                    except Exception:
                        continue
                
                # 重新设置列表
                if valid_events:
                    await self.redis_client.delete(key)
                    await self.redis_client.lpush(key, *valid_events)
                else:
                    await self.redis_client.delete(key)
            
            self.logger.info(f"清理了 {days} 天前的旧事件")
        
        except Exception as e:
            self.logger.error(f"事件清理失败: {e}")

# 预定义的事件处理器

class LoggingEventHandler(EventHandler):
    """日志记录事件处理器"""
    
    def __init__(self):
        super().__init__("logging")
    
    async def handle(self, event: Event) -> bool:
        """记录事件日志"""
        self.logger.info(f"事件: {event.event_type.value} | 用户: {event.user_id} | 数据: {event.data}")
        return True

class MetricsEventHandler(EventHandler):
    """指标统计事件处理器"""
    
    def __init__(self, redis_client=None):
        super().__init__("metrics")
        self.redis_client = redis_client
    
    async def handle(self, event: Event) -> bool:
        """更新事件指标"""
        if not self.redis_client:
            return True
        
        try:
            # 更新事件计数
            await self.redis_client.incr(f"metrics:events:{event.event_type.value}")
            
            # 按小时统计
            hour_key = f"metrics:events:hourly:{datetime.utcnow().strftime('%Y%m%d%H')}"
            await self.redis_client.hincrby(hour_key, event.event_type.value, 1)
            await self.redis_client.expire(hour_key, 7 * 24 * 3600)  # 7天过期
            
            # 按用户统计
            if event.user_id:
                user_key = f"metrics:users:{event.user_id}:events"
                await self.redis_client.hincrby(user_key, event.event_type.value, 1)
                await self.redis_client.expire(user_key, 30 * 24 * 3600)  # 30天过期
            
            return True
        
        except Exception as e:
            self.logger.error(f"指标更新失败: {e}")
            return False

class NotificationEventHandler(EventHandler):
    """通知事件处理器"""
    
    def __init__(self, notification_service=None):
        super().__init__("notification")
        self.notification_service = notification_service
    
    def can_handle(self, event_type: TradingEventType) -> bool:
        """只处理需要通知的事件类型"""
        notification_events = {
            TradingEventType.ORDER_FILLED,
            TradingEventType.ORDER_CANCELLED,
            TradingEventType.RISK_WARNING,
            TradingEventType.RISK_BLOCKED,
            TradingEventType.GATEWAY_ERROR,
            TradingEventType.STRATEGY_ERROR,
            TradingEventType.SYSTEM_ERROR
        }
        return event_type in notification_events
    
    async def handle(self, event: Event) -> bool:
        """发送通知"""
        if not self.notification_service or not event.user_id:
            return True
        
        try:
            # 根据事件类型生成通知消息
            message = self._generate_notification_message(event)
            if message:
                await self.notification_service.send_notification(
                    user_id=event.user_id,
                    message=message,
                    event_type=event.event_type.value
                )
            
            return True
        
        except Exception as e:
            self.logger.error(f"通知发送失败: {e}")
            return False
    
    def _generate_notification_message(self, event: Event) -> Optional[str]:
        """生成通知消息"""
        event_messages = {
            TradingEventType.ORDER_FILLED: "订单已完全成交",
            TradingEventType.ORDER_CANCELLED: "订单已撤销",
            TradingEventType.RISK_WARNING: f"风控警告: {event.data.get('message', '')}",
            TradingEventType.RISK_BLOCKED: f"操作被风控拦截: {event.data.get('message', '')}",
            TradingEventType.GATEWAY_ERROR: f"交易网关异常: {event.data.get('message', '')}",
            TradingEventType.STRATEGY_ERROR: f"策略执行异常: {event.data.get('message', '')}",
            TradingEventType.SYSTEM_ERROR: f"系统异常: {event.data.get('message', '')}"
        }
        
        return event_messages.get(event.event_type)